home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / 2m30src.zip / 2M-IN765.C < prev    next >
C/C++ Source or Header  |  1995-03-06  |  71KB  |  1,891 lines

  1.  
  2. /*───────────────────────────────────────────────────────────────────\
  3. │                                                                    │
  4. │     765DEBUG 4.0 - Módulo avanzado de análisis de disquetes.       │
  5. │                                                                    │
  6. │               (C) 1992-1995  Ciriaco García de Celis               │
  7. │                                                                    │
  8. \───────────────────────────────────────────────────────────────────*/
  9.  
  10.  
  11. #include <alloc.h>
  12. #include <conio.h>
  13. #include <dos.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <bios.h>
  18. #include "2m-info.h"
  19.  
  20.  
  21. #define SMAX    32768L    /* mayor sector soportado por el programa */
  22.  
  23. #define CX       12       /* color para pantalla de "memoria insuficiente" */
  24. #define CFX       0       /* color de fondo para "memoria insuficiente" */
  25. #define C765      1       /* color de '765DEBUG' */
  26. #define CM       15       /* color para el menú principal */
  27. #define CFM       3       /* color de fondo para el menú principal */
  28. #define C3D      10       /* color para el marco 3D */
  29. #define CB        2       /* color para la banda de fondo del marco 3D */
  30. #define CTIT     14       /* color del título superior */
  31. #define CVER      4       /* color de la versión */
  32. #define CB1       5       /* color 1 para botones del menú principal */
  33. #define CB2       7       /* color 2 para botones del menú principal */
  34. #define CTB1     15       /* color 1 para tinta de botones del menú principal */
  35. #define CTB2      0       /* color 2 para tinta de botones del menú principal */
  36. #define CI        1       /* color para informe en menú principal */
  37. #define CMI      11       /* color para el marco del informe en menú principal */
  38. #define CS       15       /* color para confirmar salida */
  39. #define CFS       6       /* color de fondo para confirmar salida */
  40. #define CD       15       /* color para advertencia del tamaño buffer DMA */
  41. #define CFD       6       /* color de fondo advertencia tamaño buffer DMA */
  42. #define CR       15       /* color para "ayuda" */
  43. #define CDR      14       /* color para dirección en "ayuda" */
  44. #define CFR       5       /* color de fondo para "ayuda" */
  45. #define CL       15       /* color para LeerSector */
  46. #define CFL       4       /* color de fondo para LeerSector */
  47. #define CE       15       /* color para EscribirSector */
  48. #define CFE       4       /* color de fondo para EscribirSector */
  49. #define CF       15       /* color para FormatearPista */
  50. #define CFF       5       /* color de fondo para FormatearPista */
  51. #define CIW      15       /* color para 'Leyendo ID's...' */
  52. #define CFIW      4       /* color de fondo para 'Leyendo ID's...' */
  53. #define CFI       0       /* color de fondo para lectura de ID's */
  54. #define CIC      14       /* color cabecera de lectura ID's */
  55. #define CFIC      4       /* color de fondo cabecera de lectura ID's */
  56. #define CIMS     15       /* color para milisegundos en lectura ID's */
  57. #define CIS      12       /* color para sector en lectura ID's */
  58. #define CIT      10       /* color para tamaños en lectura ID's */
  59. #define CICC     14       /* color para cilindro/cabezal en lectura ID's */
  60. #define CIST     13       /* color para registros STx en lectura ID's */
  61. #define CIB       9       /* color para mensaje barra en lectura ID's */
  62. #define CRS      15       /* color para resultados R/W/F */
  63. #define CFRS      5       /* color de fondo para resultados R/W/F */
  64. #define CFV       0       /* color de fondo para ver buffer */
  65. #define CFVM      1       /* color de fondo del menu de ver buffer */
  66. #define CVMM     11       /* color del marco del menu de ver buffer */
  67. #define CVMI     11       /* color de la información del menu de ver buffer */
  68. #define CVMS     15       /* color de la ayuda para salir del menu de ver buffer */
  69. #define CVMD     14       /* color de la información del menu de ver buffer */
  70. #define CVD      10       /* color para direcciones en menú de ver buffer */
  71. #define CVH      11       /* color para datos hexadecimales en menú de ver buffer */
  72. #define CVS       6       /* color para guión separador en menú de ver buffer */
  73. #define CVA      12       /* color para datos ASCII en menú de ver buffer */
  74. #define CVNS     15       /* color para pedir nueva sección en ver buffer */
  75. #define CFVNS     4       /* color de fondo para pedir nueva sección en ver buffer */
  76. #define CVNB     15       /* color para pedir nueva tamaño en ver buffer */
  77. #define CFVNB     5       /* color de fondo para pedir nuevo tamaño en ver buffer */
  78. #define CVMB     15       /* color para modificar en ver buffer */
  79. #define CFVMB     1       /* color de fondo para modificar en ver buffer */
  80. #define C2M      15       /* color para información de disco 2M */
  81. #define CF2M      6       /* color de fondo para información de disco 2M */
  82.  
  83.  
  84. extern   void CursorOff (void);
  85. extern   void BrilloOn (void);
  86. extern   void ventana (int, int, int, int, int, int, int);
  87. extern   int  Tecla (void);
  88. extern   void EsperaDma0 (int);
  89. extern   int  es386 (void);
  90. extern   unsigned rnd (unsigned);
  91. extern   int  input (char *, int, int, int, int);
  92. extern   int  TipoDrive (int);
  93. extern   int  Hay2M3 (void);
  94. extern   int  EsOS2 (void);
  95. extern   int  sp;
  96. extern   void v3dg (int, int, int, int, int, int, int, int, int);
  97. extern   void v3d (int, int, int, int, int);
  98. extern   void v3df (int, int, int, int, int, int, int, int);
  99. extern   void boton (int, int, int, int, int, int, char *);
  100. extern   char *dec2str (unsigned);
  101. extern   char *dec3str (unsigned);
  102. extern   char *dec5str (unsigned);
  103. extern   char *dec2strq (unsigned);
  104. extern   char *dec3strq (unsigned);
  105. extern   char *dec5strq (unsigned);
  106.  
  107.  
  108. int      infdc (void),
  109.          PeligrosoOS2 (void),
  110.          SalirConfirmado (void),
  111.          EditarTablaFmt (unsigned char *, int),
  112.          hextoi (char *);
  113. unsigned long VDMA (unsigned *);
  114. void     TestDMA (void),
  115.          DibujaOpciones (void),
  116.          DibujaValores (int, int, int, int, int),
  117.          Informe2M (int, int *, int *, int),
  118.          SeleccionarUnidad (int, int),
  119.          ResetUnidad (int),
  120.          DensidadSpecify (int),
  121.          recalibrar (int, int, int, int),
  122.          posicionar (int, int, int, int),
  123.          LeerSector (int, int, int, int, char huge *, unsigned *, int),
  124.          EscribirSector (int, int, int, int, int, char huge *),
  125.          FormatearPista (int, int, int, int, int, int),
  126.          LeerIds (int, int, int, int),
  127.          Resultados (int, int, int),
  128.          MostrarBuffer (char huge *, unsigned *),
  129.          MotorOn (int),
  130.          MotorOff (void),
  131.          outfdc (unsigned char),
  132.          EsperarInt (void),
  133.          PreparaDma (unsigned, unsigned, char huge *);
  134. char     *hex2str (int),
  135.          *ReservarMemoria (char huge **);
  136.  
  137.  
  138. void debug765()
  139. {
  140.   char     huge *buffer,    /* buffer para sector */
  141.            huge *bloque,
  142.            cad[32];
  143.   int      unidad=0, vunidad[2],
  144.            mf_mfm[2], cabezal[2],
  145.            cilindro[2], opc, t, opcion, refrescar,
  146.            PrimeraVez=1, discos=1, SalirEnOS2=0;
  147.   unsigned bytes=0;
  148.  
  149.   mf_mfm[0]=mf_mfm[1]=1; vunidad[0]=vunidad[1]=0;
  150.   cabezal[0]=cabezal[1]=cilindro[0]=cilindro[1]=0;
  151.  
  152.   t=TipoDrive(1);                       /* -1 si falla */
  153.   if (t==-1) t=peekb(0x40, 0x10) >> 6;  /* nº unidades-1 */
  154.   if (t) discos++;                      /* nº unidades disquete */
  155.  
  156.   if ((bloque=ReservarMemoria (&buffer))!=NULL) {
  157.     opcion=0; refrescar=1;
  158.     do {
  159.       BrilloOn();
  160.       if (refrescar) {
  161.         DibujaOpciones();
  162.         refrescar=0;
  163.         }
  164.       if (PrimeraVez) {         /* recalibrar unidades al */
  165.         PrimeraVez=0;           /* entrar en el programa */
  166.         SalirEnOS2=PeligrosoOS2();
  167.         if (SalirEnOS2) {
  168.           opcion=SALIR;
  169.           break;
  170.           }
  171.         TestDMA();
  172.         recalibrar (0, 0, 0, 0);
  173.         if (discos>1)
  174.           recalibrar (1, 0, 0, 0);
  175.         SeleccionarUnidad (unidad, vunidad[unidad]); /* por defecto */
  176.         }
  177.       DibujaValores (unidad, vunidad[unidad], mf_mfm[unidad],
  178.                      cilindro[unidad], cabezal[unidad]);
  179.  
  180.       CursorOff(); opc=getch();
  181.       if (!opc) opc=getch() << 8; /* usar Tecla() borraría el buffer */
  182.       switch (opc) {
  183.         case '0':  recalibrar (0, cabezal[0], vunidad[0], 1);
  184.                    if (discos>1)
  185.                      recalibrar (1, cabezal[1], vunidad[1], 1);
  186.                    cilindro[0]=cilindro[1]=0;
  187.                    SeleccionarUnidad (unidad, vunidad[unidad]);
  188.                    break;
  189.         case '1':  unidad ^= 1;
  190.                    SeleccionarUnidad (unidad, vunidad[unidad]);
  191.                    break;
  192.         case '2':  vunidad[unidad]++;
  193.                    if (vunidad[unidad]>3) vunidad[unidad]=0;
  194.                    DensidadSpecify (vunidad[unidad]);
  195.                    break;
  196.         case '3':  gotoxy (64, 19);
  197.                    strcpy (cad, dec2strq (cilindro[unidad]));
  198.                    if (input (cad, 1, 2, CI, CFM)) {
  199.                      cilindro[unidad] = atoi (cad);
  200.                      posicionar (unidad, cabezal[unidad], cilindro[unidad],
  201.                                  vunidad[unidad]);
  202.                      }
  203.                    break;
  204.         case '4':  cabezal[unidad]^=1;
  205.                    break;
  206.         case '5':  LeerIds (unidad, mf_mfm[unidad], cabezal[unidad],
  207.                             vunidad[unidad]);
  208.                    refrescar=1;
  209.                    break;
  210.         case '6':  LeerSector (unidad, mf_mfm[unidad], cilindro[unidad],
  211.                                cabezal[unidad], buffer, &bytes,
  212.                                vunidad[unidad]);
  213.                    break;
  214.         case '7':  EscribirSector (unidad, mf_mfm[unidad], vunidad[unidad],
  215.                                    cilindro[unidad], cabezal[unidad], buffer);
  216.                    break;
  217.         case '8':  MostrarBuffer (buffer, &bytes);
  218.                    refrescar=1;
  219.                    break;
  220.         case '9':  FormatearPista (unidad, mf_mfm[unidad], vunidad[unidad],
  221.                      cilindro[unidad], cabezal[unidad], vunidad[unidad]);
  222.                    break;
  223.         case 'a':
  224.         case 'A':  mf_mfm[unidad]^=1;          break;
  225.         case 'i':
  226.         case 'I':  Informe2M (unidad, &cilindro[unidad], &cabezal[unidad],
  227.                               vunidad[unidad]);
  228.                    break;
  229.         case 0x1B: if (SalirConfirmado()) opcion=SALIR; break; /* ESC */
  230.         case 0x2D00: opcion=SALIR;     break;                  /* ALT-X */
  231.         case 0x3B00: ventana (ABRIR, 3, 3, 77, 22, CR, CFR);   /* F1 */
  232.                      if (sp) {
  233.                          gotoxy ( 2, 1); cputs("  El acceso directo  a la controladora puede dejar ésta en situación no");
  234.                          gotoxy ( 2, 2); cputs("estable en caso de error  (por  ejemplo,  abortando una lectura de ID's");
  235.                          gotoxy ( 2, 3); cputs("que falla).  En ese caso las demás órdenes podrían fallar inicialmente.");
  236.                          gotoxy ( 2, 4); cputs("Si es preciso, ejecute un reset y recalibre las unidades (opción 0).");
  237.                          gotoxy ( 2, 6); cputs("  No  se  limitan,  intencionadamente,  algunas  acciones aparentemente");
  238.                          gotoxy ( 2, 7); cputs("ilógicas por parte del usuario, con objeto de lograr una herramienta de");
  239.                          gotoxy ( 2, 8); cputs("mayor potencia. En general, pulsando INTRO cuando no se sabe qué hacer,");
  240.                          gotoxy ( 2, 9); cputs("en la mayoría de las ocasiones las decisiones se toman automáticamente.");
  241.                          gotoxy ( 2,11); cputs("  Si durante las operaciones con un disco de prueba se baja la línea de");
  242.                          gotoxy ( 2,12); cputs("cambio, la BIOS podría no detectar luego el soporte. Si tiene problemas");
  243.                          gotoxy ( 2,13); cputs("con dicho disquete al salir al DOS, sáquelo y vuelva a introducirlo.");
  244.                          textcolor (CDR);
  245.                          gotoxy (21,15); cputs ("¿Usuario *REGISTRADO* con problemas?");
  246.                          gotoxy (22,16); cputs ("Mi buzón de correo electrónico es:");
  247.                          }
  248.                        else {
  249.                          gotoxy ( 2, 1); cputs("  Direct access to diskette drive controller can leave it in  undefined");
  250.                          gotoxy ( 2, 2); cputs("state if an error occurs (for example, after aborting a failed Read IDs");
  251.                          gotoxy ( 2, 3); cputs("command). In these cases, next functions can initially fail. If needed,");
  252.                          gotoxy ( 2, 4); cputs("you can reset and recalibrate drives (option 0).");
  253.                          gotoxy ( 2, 6); cputs("  Some  apparently  incorrect  actions  performed  by  the user are not");
  254.                          gotoxy ( 2, 7); cputs("intentionally skipped,  in order to increase the power of this program.");
  255.                          gotoxy ( 2, 8); cputs("Generally,  pressing ENTER key when you don't know what to do,  in most");
  256.                          gotoxy ( 2, 9); cputs("cases most decisions are automatically adopted by the program.");
  257.                          gotoxy ( 2,11); cputs("  If during some diskette operations the disk change line is reset, the");
  258.                          gotoxy ( 2,12); cputs("system BIOS may not detect disk media in future.  If  you have problems");
  259.                          gotoxy ( 2,13); cputs("with such disk after exit to DOS, extract and then insert it again.");
  260.                          textcolor (CDR);
  261.                          gotoxy (21,15); cputs ("A *REGISTERED* user with problems?");
  262.                          gotoxy (24,16); cputs ("My electronic mailboxes are:");
  263.                          }
  264.                      gotoxy (26,17); cputs ("Internet  ciri@gui.uva.es");
  265.                      gotoxy (26,18); cputs ("Fidonet   2:341/21.8");
  266.                      CursorOff();
  267.                      Tecla();
  268.                      ventana (CERRAR, 3, 3, 77, 22, 0, 0);
  269.                      break;
  270.         }
  271.     } while (opcion!=SALIR);
  272.   }
  273.  
  274.   if ((!SalirEnOS2) && (bloque!=NULL)) {
  275.     pokeb (0x40, 0x94, cilindro[0]);
  276.     pokeb (0x40, 0x95, cilindro[1]);
  277.     outportb (FD_DCR, peekb(0x40, 0x8B) >> 6);  /* velocidad normal */
  278.     }
  279.   if (bloque!=NULL) farfree ((char far *) bloque);
  280.   clrscr();
  281. }
  282.  
  283.  
  284. char *ReservarMemoria (char huge **buffer)
  285. {
  286.   unsigned long dir;
  287.   char     *bloque, *bf;
  288.  
  289.   *buffer=bloque=farmalloc(SMAX << 1);
  290.   bf=farmalloc(4096L);
  291.  
  292.   if ((*buffer==NULL) || (bf==NULL)) {
  293.     if (*buffer!=NULL) farfree ((char far *) *buffer);
  294.     textbackground (CFX); textcolor (CX); clrscr();
  295.     gotoxy (24,12);
  296.     if (sp)
  297.         cputs ("Memoria insuficiente para 765DEBUG");
  298.       else
  299.         cputs ("Insufficient memory for 765DEBUG");
  300.     CursorOff();
  301.     delay (2000);
  302.     return (NULL);
  303.     }
  304.  
  305.   farfree (bf);  /* liberar bloque "de seguridad" */
  306.  
  307.   dir = ((unsigned long) FP_SEG(*buffer) <<4) + FP_OFF(*buffer);
  308.   if ( (dir>>16) != ( (dir+SMAX) >> 16) )
  309.      *buffer+=SMAX;    /* evitar buffer entre dos páginas de DMA */
  310.  
  311.   return (bloque);
  312. }
  313.  
  314.  
  315. void DibujaOpciones()
  316. {
  317.   textbackground (CFM); textcolor(CM); clrscr();
  318.   v3dg (3, 2, 76, 12, 1, 2, C3D, CFM, CB);
  319.   v3d  (3, 2, 76, 12, 2);
  320.   textcolor (C765); gotoxy (2,1); cputs("█▀▀▀█ █▀▀██ █▀▀▀▀     █       █                   "); textcolor(CVER); cputs(" ▄   ▄   ▄▄▄▄▄");
  321.   textcolor (C765); gotoxy (2,2); cputs("    █ █     █         █       █           ▄▄▄▄▄─┼─"); textcolor(CVER); cputs(" █   █   █   █");
  322.   textcolor (C765); gotoxy (2,3); cputs("   ██ █▀▀██ ▀▀▀██ █▀▀▀█ █▀▀▀█ █▀▀▀█ █   █ █   █   "); textcolor(CVER); cputs(" █▄▄▄█▄  █  ▄█");
  323.   textcolor (C765); gotoxy (2,4); cputs("   ██ █  ██    ██ █   █ █▀▀▀▀ █   █ █   █ █   █   "); textcolor(CVER); cputs("    ██   █  ██");
  324.   textcolor (C765); gotoxy (2,5); cputs("   ▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀█   "); textcolor(CVER); cputs("    ▀▀ ▀ ▀▀▀▀▀");
  325.   textcolor (C765); gotoxy (2,6); cputs("                                            █▄█   ");
  326.   gotoxy (2,6); textcolor (CTIT);
  327.   if (sp)
  328.       cputs("ANALISIS AVANZADO A BAJO NIVEL DE DISQUETES");
  329.     else
  330.       cputs(" ADVANCED LOW LEVEL DISK ANALYSIS UTILITY");
  331.   window (1,1,80,25);
  332.   if (sp) {
  333.       boton ( 3,15,CB1,CTB1,CM,CFM," 0 "); cputs (" Recalibrar unidades + reset.");
  334.       boton ( 3,16,CB2,CTB2,CM,CFM," 1 "); cputs (" Seleccionar unidad.");
  335.       boton ( 3,17,CB1,CTB1,CM,CFM," 2 "); cputs (" Seleccionar densidad + enviar specify.");
  336.       boton ( 3,18,CB2,CTB2,CM,CFM," 3 "); cputs (" Posicionar cabezal.");
  337.       boton ( 3,19,CB1,CTB1,CM,CFM," 4 "); cputs (" Cambiar de cabezal.");
  338.       boton ( 3,20,CB2,CTB2,CM,CFM," 5 "); cputs (" Leer ID's.");
  339.       boton ( 3,21,CB1,CTB1,CM,CFM," 6 "); cputs (" Leer sector al buffer interno.");
  340.       boton ( 3,22,CB2,CTB2,CM,CFM," 7 "); cputs (" Escribir sector del buffer interno.");
  341.       boton ( 3,23,CB1,CTB1,CM,CFM," 8 "); cputs (" Ver o editar sector del buffer interno.");
  342.       boton ( 3,24,CB2,CTB2,CM,CFM," 9 "); cputs (" Formatear pista.");
  343.       boton (51,22,CB1,CTB1,CM,CFM," A "); cputs (" Conmutar MF/MFM.");
  344.       boton (51,23,CB2,CTB2,CM,CFM," I "); cputs (" Información disco 2M.");
  345.       boton (51,24,CB1,CTB1,CM,CFM,"ESC"); cputs (" Salir (ALT-X rápido).");
  346.       }
  347.     else {
  348.       boton ( 3,15,CB1,CTB1,CM,CFM," 0 "); cputs (" Recalibrate drives & reset.");
  349.       boton ( 3,16,CB2,CTB2,CM,CFM," 1 "); cputs (" Select drive.");
  350.       boton ( 3,17,CB1,CTB1,CM,CFM," 2 "); cputs (" Select density & send specify.");
  351.       boton ( 3,18,CB2,CTB2,CM,CFM," 3 "); cputs (" Seek to new track.");
  352.       boton ( 3,19,CB1,CTB1,CM,CFM," 4 "); cputs (" Select other head.");
  353.       boton ( 3,20,CB2,CTB2,CM,CFM," 5 "); cputs (" Read ID's.");
  354.       boton ( 3,21,CB1,CTB1,CM,CFM," 6 "); cputs (" Read sector into internal buffer.");
  355.       boton ( 3,22,CB2,CTB2,CM,CFM," 7 "); cputs (" Write internal's buffer sector.");
  356.       boton ( 3,23,CB1,CTB1,CM,CFM," 8 "); cputs (" View or edit internal's buffer sector.");
  357.       boton ( 3,24,CB2,CTB2,CM,CFM," 9 "); cputs (" Format track.");
  358.       boton (51,22,CB1,CTB1,CM,CFM," A "); cputs (" Change MF/MFM.");
  359.       boton (51,23,CB2,CTB2,CM,CFM," I "); cputs (" 2M disk information.");
  360.       boton (51,24,CB1,CTB1,CM,CFM,"ESC"); cputs (" Exit (ALT-X quit!).");
  361.       }
  362.  
  363.   v3df (51, 14, 26, 8, 1, 1, CMI, CFM);
  364. }
  365.  
  366.  
  367. void DibujaValores (unidad, vunidad, mf_mfm, cilindro, cabezal)
  368. {
  369.   textcolor (CI); textbackground (CFM);
  370.   gotoxy (55, 16); if (sp) cputs("Unidad "); else cputs("Drive ");
  371.   putch(unidad+'A'); putch(':');
  372.   gotoxy (55, 17);
  373.   switch (vunidad) {
  374.     case 2: cputs ("250 Kbit"); break;
  375.     case 1: cputs ("300 Kbit"); break;
  376.     case 0: cputs ("500 Kbit"); break;
  377.     default:  cputs ("1 Mbit"); break;
  378.     }
  379.   if (sp) cputs("/seg"); else cputs("/sec");
  380.   if (mf_mfm) cputs(" MFM   "); else cputs(" MF   ");
  381.   gotoxy (59, 18);
  382.   switch (vunidad) {
  383.     case 1:  cputs("360K     "); break;
  384.     case 2:  cputs("720K     "); break;
  385.     case 3:  cputs("2.88M    "); break;
  386.     default: cputs("1.2/1.44M"); break;
  387.     }
  388.   gotoxy (55, 19);
  389.   if (sp) cputs("Cilindro "); else cputs("Cylinder ");
  390.   cputs (dec2strq(cilindro)); cputs("  ");
  391.   gotoxy (67, 19);
  392.   if (sp) cputs("Cara "); else cputs("Side ");
  393.   cputs (dec2strq(cabezal));
  394. }
  395.  
  396.  
  397. int PeligrosoOS2()
  398. {
  399.   int largarse=0, t;
  400.  
  401.   if (EsOS2()) {
  402.     ventana (ABRIR, 15, 8, 64, 19, CS, CFS);
  403.     if (sp) {
  404.         gotoxy (5, 2); cputs("Esta sesión DOS está corriendo bajo OS/2");
  405.         gotoxy (5, 4); cputs("765DEBUG puede funcionar bajo  OS/2,  pero");
  406.         gotoxy (3, 5); cputs("sus continuos accesos al hardware de disco y");
  407.         gotoxy (3, 6); cputs("el control que realiza  OS/2  de los puertos");
  408.         gotoxy (3, 7); cputs("convierten la tarea en algo conflictiva.");
  409.         gotoxy (8, 9); cputs("INTRO - CONTINUAR     ESC - SALIR");
  410.         }
  411.       else {
  412.         gotoxy (6, 2); cputs("This DOS session is running under OS/2");
  413.         gotoxy (5, 4); cputs("765DEBUG can work with OS/2 loaded, but it");
  414.         gotoxy (3, 5); cputs("continuous and direct disk hardware  access,");
  415.         gotoxy (3, 6); cputs("and the I/O ports control performed by  OS/2");
  416.         gotoxy (3, 7); cputs("turn its functions a little conflictive.");
  417.         gotoxy (8, 9); cputs("ENTER - CONTINUE      ESC - EXITS");
  418.         }
  419.     CursorOff(); t = Tecla();
  420.     if (t!=13) largarse=1;
  421.     ventana (CERRAR, 15, 8, 64, 19, 0, 0);
  422.     }
  423.  
  424.   return (largarse);
  425. }
  426.  
  427.  
  428. void TestDMA (void)
  429. {
  430.   unsigned emm;
  431.   unsigned long bytes;
  432.  
  433.   if ((bytes=VDMA(&emm)) < SMAX) {
  434.     ventana (ABRIR, 21, 6, 61, 20, CD, CFD);
  435.     if (sp) {
  436.         gotoxy (17,1); cputs("AVISO");
  437.         gotoxy (2, 3); cputs("El buffer para transferencias con DMA");
  438.         gotoxy (2, 4); cputs("de su  controlador de memoria  admite");
  439.         gotoxy (2, 5); cputs("sólo "); cputs (dec5strq((unsigned) bytes));
  440.                        cputs (" bytes (");
  441.                        cputs(dec2strq((unsigned) bytes/1024)); cputs(" Kb).");
  442.         gotoxy (2, 7); cputs("El sistema podría estrellarse o puede");
  443.         gotoxy (2, 8); cputs("salir un mensaje de su controlador de");
  444.         gotoxy (2, 9); cputs("memoria si trabaja con sectores de un");
  445.         gotoxy (2,10); cputs("tamaño superior (y sólo en ese caso).");
  446.         if (emm == 20805) {
  447.           gotoxy (2,12); cputs("Con su controlador (QEMM) bastaría en");
  448.           gotoxy (2,13); cputs("ese caso añadir la opción DMA=Kbytes.");
  449.           }
  450.         }
  451.       else {
  452.         gotoxy (16,1); cputs("WARNING");
  453.         gotoxy (2, 3); cputs("The current maximum  DMA  buffer size");
  454.         gotoxy (2, 4); cputs("supported by your memory manager, has");
  455.         gotoxy (2, 5); cputs("only "); cputs (dec5strq((unsigned) bytes));
  456.                        cputs (" bytes (");
  457.                        cputs(dec2strq((unsigned) bytes/1024)); cputs(" Kb).");
  458.         gotoxy (2, 7); cputs("The system may hangs;  or your memory");
  459.         gotoxy (2, 8); cputs("manager can print an error message if");
  460.         gotoxy (2, 9); cputs("you work with sectors bigger than the");
  461.         gotoxy (2,10); cputs("buffer size (and only in this case).");
  462.         if (emm == 20805) {
  463.           gotoxy (2,12); cputs("With your EMM (QEMM) you can,  if you");
  464.           gotoxy (2,13); cputs("need it, to add a DMA=Kbytes option.");
  465.           }
  466.         }
  467.     CursorOff(); getch();
  468.     ventana (CERRAR, 21, 6, 61, 20, 0, 0);
  469.     }
  470. }
  471.  
  472.  
  473. unsigned long VDMA (unsigned *emm)
  474. {
  475.   union    REGS r;
  476.   struct   SREGS s;
  477.   unsigned long bytes;
  478.  
  479.   bytes = 65536L;    /* supuesto que no hay problemas con el DMA */
  480.   *emm  = 0;         /* supuesto que no hay controlador de memoria */
  481.  
  482.   if (es386()) {
  483.     r.x.ax = 0x354B;
  484.     int86x (0x21, &r, &r, &s);
  485.     if ((s.es | r.x.bx) && (s.es != 0xFFFF) && (r.x.bx != 0xFFFF)) {
  486.       r.x.ax = 0x8102;
  487.       r.x.dx = r.x.si = r.x.di = 0;
  488.       int86 (0x4B, &r, &r);
  489.       if ((!(r.x.flags & 1)) && (r.x.si | r.x.di)) {
  490.         bytes = ((unsigned long) r.x.si << 16) | r.x.di;
  491.         *emm  = r.x.bx;
  492.         }
  493.       }
  494.     }
  495.   return (bytes);
  496. }
  497.  
  498.  
  499. int SalirConfirmado()
  500. {
  501.   int salir, t;
  502.  
  503.   t = peekb(0x40, 0x49) & 0x7F;
  504.  
  505.   ventana (ABRIR, 29, 9, 60, 15, CS, CFS);
  506.   textcolor (CS);
  507.   if (sp) {
  508.       gotoxy (4,2); cputs("¿Seguro que desea salir?");
  509.       gotoxy (3,4); cputs("Pulse ");
  510.       }
  511.     else {
  512.       gotoxy (6,2); cputs("Are you sure to exit?");
  513.       gotoxy (3,4); cputs("Press ");
  514.       }
  515.   if (t!=7) {
  516.       textcolor (CFS+BLINK); textbackground (CS);
  517.       }
  518.     else {
  519.       textcolor (0); textbackground (7);
  520.       }
  521.   if (sp) {
  522.       cputs ("INTRO");
  523.       textcolor (CS); textbackground (CFS); cputs(" para confirmar");
  524.       }
  525.     else {
  526.       cputs ("ENTER");
  527.       textcolor (CS); textbackground (CFS); cputs(" key to confirm");
  528.       }
  529.   CursorOff();
  530.   t=Tecla();
  531.   if ((t==13) || (t==0x2D00)) salir=1; else salir=0;
  532.   ventana (CERRAR, 29, 9, 60, 15, 0, 0);
  533.   return (salir);
  534. }
  535.  
  536.  
  537. void Informe2M (int unidad, int *cilindro, int *cabezal, int vunidad)
  538. {
  539.   Boot   sector0, virtual;
  540.   int    i, error, anio, mes, dia, hora, min, seg, dif;
  541.  
  542.   *cilindro = *cabezal = 0;   /* terminaremos en pista 0 */
  543.  
  544.   outportb (FD_DCR, peekb(0x40, 0x8B) >> 6);  /* velocidad normal */
  545.  
  546.   ventana (ABRIR, 22, 7, 57, 16, C2M, CF2M);
  547.  
  548.   if (sp) {
  549.       gotoxy (9, 1);
  550.       cputs("INFORME UNIDAD "); putch(unidad+'A'); putch(':');
  551.       }
  552.     else {
  553.       gotoxy (10,1);
  554.       cputs("DRIVE "); putch(unidad+'A'); putch(':'); cputs(" REPORT");
  555.       }
  556.  
  557.   if (!Hay2M3()) {
  558.       if (sp) {
  559.           gotoxy (5,4); cputs("2M ó 2MX 3.X no instalado");
  560.           gotoxy (8,6); cputs("Imposible informar");
  561.           }
  562.         else {
  563.           gotoxy (6,4); cputs("2M ó 2MX 3.X not loaded");
  564.           gotoxy (5,6); cputs("Information not available");
  565.           }
  566.       }
  567.     else {
  568.       error=biosdisk(2, unidad, 0x80, 0, 1, 1, §or0);
  569.       if (error) {
  570.         biosdisk (0, unidad, 0, 0, 1, 1, §or0);
  571.         error=biosdisk(2, unidad, 0x80, 0, 1, 1, §or0);
  572.         }
  573.       if (error) error=biosdisk(2, unidad, 0x80, 0, 1, 1, §or0);
  574.       if (error==4) {
  575.           if (sp) {
  576.               gotoxy (4,5); cputs("El disquete no es de tipo 2M");
  577.               }
  578.             else {
  579.               gotoxy (4,5); cputs("Diskette is not 2M formatted");
  580.               }
  581.           }
  582.       else if (error) {
  583.         if (sp) {
  584.             gotoxy (8,4); cputs("Unidad no preparada");
  585.             gotoxy (8,5); cputs("o disquete extraño.");
  586.             }
  587.           else {
  588.             gotoxy (10,4); cputs("Drive not ready");
  589.             gotoxy (7,5); cputs("or strange disk format.");
  590.             }
  591.         }
  592.       else {
  593.         gotoxy (3,3); if (sp) cputs("Tipo de disco:    ");
  594.           else cputs("Disk type:       ");
  595.         for (i=0; i<8; i++) putch(sector0.IdSis[i]);
  596.  
  597.         gotoxy (3,4); if (sp) cputs("Capacidad:        ");
  598.           else cputs("Disk size:       ");
  599.         cputs (dec5strq(sector0.NumSect/(1024/sector0.BytesSect)));
  600.         cputs(" Kb");
  601.  
  602.         gotoxy (3,5); if (sp) cputs("Versión formato:  ");
  603.           else cputs("Format release:  ");
  604.         cputs (dec2strq(sector0.VersionFmt));
  605.  
  606.         gotoxy (3,6); if (sp) cputs("Fecha formateo:   ");
  607.           else cputs("Format date:     ");
  608.  
  609.         if (sector0.Flags & 1) {
  610.             anio=1980+(sector0.FechaF>>9);
  611.             mes=(sector0.FechaF>>5) & 15;
  612.             dia=sector0.FechaF & 31;
  613.             if (sp) {
  614.                 cputs (dec2strq(dia)); putch('/');
  615.                 cputs (dec2str(mes)); putch('/');
  616.                 cputs (dec5strq(anio));
  617.                 }
  618.               else {
  619.                 cputs (dec2strq(mes)); putch('/');
  620.                 cputs (dec2str(dia)); putch('/');
  621.                 cputs (dec5strq(anio));
  622.                 }
  623.             }
  624.           else {
  625.             if (sp) cputs("No disponible"); else cputs("Not available");
  626.             }
  627.  
  628.         gotoxy (3,7); if (sp) cputs("Hora formateo:    ");
  629.           else cputs("Format time:     ");
  630.  
  631.         if (sector0.Flags & 1) {
  632.             hora=sector0.HoraF>>11;
  633.             min=(sector0.HoraF>>5) & 63;
  634.             seg=(sector0.HoraF & 31) << 1;
  635.                 cputs (dec2str(hora)); putch(':');
  636.                 cputs (dec2str(min)); putch(':');
  637.                 cputs (dec2str(seg));
  638.             }
  639.           else {
  640.             if (sp) cputs("No disponible"); else cputs("Not available");
  641.             }
  642.       }
  643.     }
  644.  
  645.   CursorOff();
  646.   i = Tecla();
  647.   ventana (CERRAR, 22, 7, 57, 16, 0, 0);
  648.  
  649.   SeleccionarUnidad (unidad, vunidad); /* restaurar condiciones iniciales */
  650. }
  651.  
  652.  
  653. void SeleccionarUnidad (unidad, vunidad)
  654. {
  655.   pokeb(0x40,0x40,0xFF);
  656.   outportb (FD_DOR, 1<<(unidad+4) | 4+8 | unidad);
  657.   pokeb (0x40, 0x3F, peekb(0x40, 0x3F) | (1 << unidad));
  658.  
  659.   DensidadSpecify (vunidad);
  660.  
  661.   MotorOff();
  662. }
  663.  
  664.  
  665. void ResetUnidad (unidad)
  666. {
  667.   int i;
  668.  
  669.   pokeb (0x40, 0x3E, peekb (0x40, 0x3E) & 0x7F);
  670.  
  671.   outportb (FD_DOR, 1<<(unidad+4) | unidad | 8);     /* reset */
  672.   delay (2);
  673.   outportb (FD_DOR, 1<<(unidad+4) | unidad | 8+4); /* fin reset */
  674.  
  675.   EsperarInt();        /* esperar interrupción */
  676.  
  677.   outfdc (8);          /* comando 'leer estado de interrupciones' */
  678.   (void) infdc();      /* leer y desechar resultado */
  679.   (void) infdc();
  680.  
  681.   MotorOff();
  682. }
  683.  
  684.  
  685. void DensidadSpecify (int vunidad)
  686. {
  687.   outportb (FD_DCR, vunidad);  /* seleccionar densidad */
  688.  
  689.   outfdc (3);           /* comando Specify */
  690.   if (vunidad==3)
  691.       outfdc (0xAF);    /* tiempo de acceso pista-pista y head unload */
  692.     else if (!vunidad)
  693.       outfdc (0xBF);
  694.     else
  695.       outfdc (0xDF);
  696.   outfdc (2);           /* head load time = 1; modo DMA */
  697. }
  698.  
  699.  
  700. void recalibrar (unidad, cabezal, vunidad, pausa)
  701. {
  702.   int  recal, res, pis;
  703.  
  704.   ventana (ABRIR, 30, 10, 50, 17, 15, 1);
  705.  
  706.   gotoxy (3, 3);
  707.   if (sp) cputs("Recalibrando "); else cputs("Recalibrate ");
  708.   putch(unidad+'A'); putch(':');
  709.   CursorOff();
  710.  
  711.   MotorOn (unidad);  /* asegurar que el motor está en marcha */
  712.   SeleccionarUnidad (unidad, vunidad);
  713.   MotorOn (unidad);
  714.  
  715.   ResetUnidad (unidad);                 /* aprovechar para resetear */
  716.   ResetUnidad (unidad);
  717.   DensidadSpecify (vunidad);
  718.  
  719.       /**** Recalibrar hasta dos veces si es preciso ****/
  720.  
  721.   for (recal=0; recal<2; recal++) {
  722.  
  723.     outfdc (7);                        /* comando de recalibrado */
  724.     outfdc (cabezal << 2 | unidad);    /* byte 1 de dicho comando */
  725.  
  726.     EsperarInt();        /* esperar interrupción */
  727.  
  728.     outfdc (8);          /* comando 'leer estado de interrupciones' */
  729.  
  730.     res=infdc();         /* leer resultado */
  731.     pis=infdc();
  732.  
  733.     if (!recal) clrscr();
  734.  
  735.     gotoxy (5, 1+recal*2);
  736.  
  737.     if ((res>=0) && (pis>=0)) {
  738.         cputs ("ST0 = 0x"); cputs (hex2str(res));
  739.         gotoxy (5, 2+recal*2);
  740.         if (sp) cputs ("Pista = "); else cputs ("Track = ");
  741.         cputs (dec2strq(pis));
  742.         }
  743.       else
  744.         cputs ("ST0 = ??");
  745.  
  746.     if (!((res ^ 32) & (0xF0))) break;  /* resultado correcto */
  747.   }
  748.  
  749.   MotorOff();
  750.   if (recal<2) {     /* sin fallo */
  751.       CursorOff();
  752.       if (pausa) delay(750);
  753.       }
  754.     else {
  755.       gotoxy (3, 6);
  756.       if (sp) cputs ("Pulsa una tecla"); else cputs (" Press any key ");
  757.       CursorOff(); Tecla();
  758.       }
  759.   ventana (CERRAR, 30, 10, 50, 17, 0, 0);
  760. }
  761.  
  762.  
  763. void posicionar (unidad, cabezal, cilindro, vunidad)
  764. {
  765.   int  res, pis;
  766.  
  767.   ventana (ABRIR, 30, 9, 50, 14, 15, 1);
  768.  
  769.   gotoxy (3, 2);
  770.   if (sp) cputs("Posicionando "); else cputs("    Seek ");
  771.   putch(unidad+'A'); putch(':');
  772.   CursorOff();
  773.  
  774.   MotorOn (unidad);  /* asegurar que el motor está en marcha */
  775.   SeleccionarUnidad (unidad, vunidad);
  776.   MotorOn (unidad);
  777.  
  778.       /**** Desplazar cabezal hasta la pista ****/
  779.  
  780.   outfdc (0xF);                       /* comando 'Seek' */
  781.   outfdc (cabezal << 2 | unidad);     /* byte 1 de dicho comando */
  782.   outfdc (cilindro);
  783.  
  784.   EsperarInt();          /* esperar interrupción */
  785.  
  786.   outfdc (8);            /* comando 'leer estado de interrupciones' */
  787.   res=infdc();
  788.   pis=infdc();
  789.  
  790.   clrscr(); gotoxy (5, 1);
  791.  
  792.   if ((res>=0) && (pis>=0)) {
  793.       cputs ("ST0 = 0x"); cputs (hex2str(res)); gotoxy (5, 2);
  794.       if (sp) cputs ("Pista = "); else cputs ("Track = ");
  795.       cputs (dec2strq(pis)); gotoxy (3, 4);
  796.       }
  797.     else
  798.       cputs ("ST0 = ??");
  799.  
  800.   MotorOff();
  801.  
  802.   if (!(res & 0xC0)) {
  803.       CursorOff();
  804.       delay(750);
  805.       }
  806.     else {
  807.       if (sp) cputs ("Pulsa una tecla"); else cputs (" Press any key ");
  808.       CursorOff(); Tecla();
  809.       }
  810.  
  811.   ventana (CERRAR, 30, 9, 50, 14, 0, 0);
  812. }
  813.  
  814.  
  815. void LeerSector (unidad, mf_mfm, cilindro, cabezal, buffer, bytes, vunidad)
  816. char      huge *buffer;
  817. unsigned  *bytes;
  818. {
  819.   static   sector=1, tsector=2, t128=128;
  820.   unsigned t;
  821.   char     cad[32];
  822.  
  823.   ventana (ABRIR, 23, 7, 65, 21, CL, CFL);
  824.  
  825.   if (sp) {
  826.       gotoxy (12,1);
  827.       cputs("LECTURA DE SECTOR");
  828.       }
  829.     else {
  830.       gotoxy (16,1);
  831.       cputs("SECTOR READ");
  832.       }
  833.  
  834.   gotoxy (2,3); cputs("Sector: ");
  835.   strcpy (cad, dec3strq (sector));
  836.   if (!input (cad, 1, 3, CL, CFL)) goto AbortaLectura;
  837.   sector = atoi (cad); if (sector>255) sector=255;
  838.  
  839.   gotoxy (2, 5); if (sp) cputs("Tamaño de sector:"); else cputs("Sector size:");
  840.   gotoxy (2, 6); cputs("  0 -> 1-128 bytes    5 ->  4096 bytes");
  841.   gotoxy (2, 7); cputs("  1 ->   256 bytes    6 ->  8192 bytes");
  842.   gotoxy (2, 8); cputs("  2 ->   512 bytes    7 -> 16384 bytes");
  843.   gotoxy (2, 9); cputs("  3 ->  1024 bytes    8 -> 32768 bytes");
  844.   gotoxy (2,10); cputs("  4 ->  2048 bytes    Val");
  845.   if (sp) cputs("or: "); else cputs("ue: ");
  846.   strcpy (cad, dec2strq (tsector));
  847.   if (!input (cad, 1, 2, CL, CFL)) goto AbortaLectura;
  848.   tsector = atoi (cad);
  849.  
  850.   if (tsector==0) {
  851.     gotoxy (24, 10); if (sp) cputs("Indica"); else cputs("Select");
  852.     cputs(" 1-128: ");
  853.     strcpy (cad, dec3strq (t128));
  854.     if (!input (cad, 1, 3, CL, CFL)) goto AbortaLectura;
  855.     t128 = atoi (cad); if (t128>255) t128=255;
  856.     }
  857.  
  858.   gotoxy (7,12); if (sp) cputs("Cilindro: "); else cputs("Cylinder: ");
  859.   strcpy (cad, dec3strq (cilindro));
  860.   if (!input (cad, 1, 3, CL, CFL)) goto AbortaLectura;
  861.   cilindro = atoi (cad); if (cilindro>255) cilindro=255;
  862.  
  863.   gotoxy (25,12); if (sp) cputs("Cara: "); else cputs("Side: ");
  864.   strcpy (cad, dec3strq (cabezal));
  865.   if (!input (cad, 1, 3, CL, CFL)) goto AbortaLectura;
  866.   cabezal = atoi (cad); if (cabezal>255) cabezal=255;
  867.  
  868.   clrscr();
  869.   gotoxy (17, 6); if (sp) cputs("Leyendo..."); else cputs("Reading...");
  870.  
  871.   for (t=0; t<SMAX; t+=2) {
  872.     buffer[t]=0x5A; buffer[t+1]=0xA5;  /* "borrar" el buffer */
  873.     }
  874.  
  875.   MotorOn (unidad);
  876.   SeleccionarUnidad (unidad, vunidad);
  877.   MotorOn (unidad);
  878.  
  879.   *bytes = tsector? (unsigned) 128 << tsector: t128;
  880.  
  881.   PreparaDma (0x46, *bytes, buffer);
  882.  
  883.   outfdc (0x06 | mf_mfm << 6);     /* comando para leer */
  884.   outfdc (cabezal << 2 | unidad);  /* byte 1 de dicho comando */
  885.   outfdc (cilindro);
  886.   outfdc (cabezal);
  887.   outfdc (sector);
  888.   outfdc (tsector);
  889.   outfdc (sector);
  890.   outfdc (1);                     /* GAP para leer: poco importante */
  891.   outfdc (t128);                  /* tamaño si tsector=0 */
  892.  
  893.   EsperarInt();                   /* esperar interrupción */
  894.  
  895.   ventana (CERRAR, 23, 7, 65, 21, 0, 0);
  896.   Resultados (LEER, unidad, cabezal);
  897.  
  898.   goto FinLectura;
  899.  
  900.   AbortaLectura: ventana (CERRAR, 23, 7, 65, 21, 0, 0);
  901.   FinLectura: ;
  902. }
  903.  
  904.  
  905. void EscribirSector (unidad, mf_mfm, vunidad, cilindro, cabezal, buffer)
  906. char huge *buffer;
  907. {
  908.   static   sector=1, tsector=2, t128=128, wreset=0, dmacnt=12335;
  909.   char     cad[32];
  910.  
  911.   ventana (ABRIR, 23, 5, 65, 23, CE, CFE);
  912.  
  913.   if (sp) {
  914.       gotoxy (11,1);
  915.       cputs("ESCRITURA DE SECTOR");
  916.       }
  917.     else {
  918.       gotoxy (16,1);
  919.       cputs("SECTOR WRITE");
  920.       }
  921.  
  922.   gotoxy (2,3); cputs("Sector: ");
  923.   strcpy (cad, dec3strq (sector));
  924.   if (!input (cad, 1, 3, CE, CFE)) goto AbortaEscritura;
  925.   sector = atoi (cad); if (sector>255) sector=255;
  926.  
  927.   gotoxy (2, 5); if (sp) cputs("Tamaño de sector:"); else cputs("Sector size:");
  928.   gotoxy (2, 6); cputs("  0 -> 1-128 bytes    5 ->  4096 bytes");
  929.   gotoxy (2, 7); cputs("  1 ->   256 bytes    6 ->  8192 bytes");
  930.   gotoxy (2, 8); cputs("  2 ->   512 bytes    7 -> 16384 bytes");
  931.   gotoxy (2, 9); cputs("  3 ->  1024 bytes    8 -> 32768 bytes");
  932.   gotoxy (2,10); cputs("  4 ->  2048 bytes    Val");
  933.   if (sp) cputs("or: "); else cputs("ue: ");
  934.   strcpy (cad, dec2strq (tsector));
  935.   if (!input (cad, 1, 2, CE, CFE)) goto AbortaEscritura;
  936.   tsector = atoi (cad);
  937.  
  938.   if (tsector==0) {
  939.     gotoxy (24, 10); if (sp) cputs("Indica"); else cputs("Select");
  940.     cputs(" 1-128: ");
  941.     strcpy (cad, dec3strq (t128));
  942.     if (!input (cad, 1, 3, CE, CFE)) goto AbortaEscritura;
  943.     t128 = atoi (cad); if (t128>255) t128=255;
  944.     }
  945.  
  946.   gotoxy (7,12); if (sp) cputs("Cilindro: "); else cputs("Cylinder: ");
  947.   strcpy (cad, dec3strq (cilindro));
  948.   if (!input (cad, 1, 3, CE, CFE)) goto AbortaEscritura;
  949.   cilindro = atoi (cad); if (cilindro>255) cilindro=255;
  950.  
  951.   gotoxy (25,12); if (sp) cputs("Cara: "); else cputs("Side: ");
  952.   strcpy (cad, dec3strq (cabezal));
  953.   if (!input (cad, 1, 3, CE, CFE)) goto AbortaEscritura;
  954.   cabezal = atoi (cad); if (cabezal>255) cabezal=255;
  955.  
  956.   gotoxy (2, 14);
  957.   if (sp)
  958.       cputs("¿Escritura normal sin reset? (S/N): ");
  959.     else
  960.       cputs("Normal write without reset? (Y/N): ");
  961.   if (wreset) strcpy (cad, "N"); else strcpy (cad, sp?"S":"Y");
  962.   if (!input (cad, 0, 1, CE, CFE)) goto AbortaEscritura;
  963.   if ((cad[0] | 32) == 'n') wreset=1; else wreset=0;
  964.  
  965.   if (wreset) {
  966.     gotoxy (2, 16);
  967.     if (sp)
  968.         cputs("Valor del contador del DMA: ");
  969.       else
  970.         cputs("Value for DMA count: ");
  971.     strcpy (cad, dec5strq (dmacnt));
  972.     if (!input (cad, 1, 5, CE, CFE)) goto AbortaEscritura;
  973.     dmacnt = atoi (cad);
  974.     }
  975.  
  976.   clrscr();
  977.   gotoxy (15, 8);
  978.   if (sp) cputs("Escribiendo..."); else cputs("  Writing...");
  979.  
  980.   MotorOn (unidad);
  981.   SeleccionarUnidad (unidad, vunidad);
  982.   MotorOn (unidad);
  983.  
  984.   PreparaDma (0x4A, wreset? dmacnt: tsector? 128 << tsector: 0, buffer);
  985.  
  986.   outfdc (0x05 | mf_mfm << 6);     /* comando para escribir */
  987.   outfdc (cabezal << 2 | unidad);  /* byte 1 de dicho comando */
  988.   outfdc (cilindro);
  989.   outfdc (cabezal);
  990.   outfdc (sector);
  991.   outfdc (tsector);
  992.   outfdc (sector);
  993.   outfdc (1);                      /* GAP mínimo */
  994.   outfdc (t128);                   /* tamaño si tsector=0 */
  995.  
  996.   if (wreset) {
  997.       EsperaDma0 (unidad);         /* con reset precario */
  998.       ResetUnidad (unidad);        /* reset en condiciones */
  999.       SeleccionarUnidad (unidad, vunidad);
  1000.       }
  1001.     else EsperarInt();
  1002.  
  1003.   ventana (CERRAR, 23, 5, 65, 23, 0, 0);
  1004.  
  1005.   if (!wreset) Resultados (ESCRIBIR, unidad, cabezal);
  1006.  
  1007.   goto FinEscritura;
  1008.  
  1009.   AbortaEscritura: ventana (CERRAR, 23, 5, 65, 23, 0, 0);
  1010.   FinEscritura: ;
  1011. }
  1012.  
  1013.  
  1014. void FormatearPista (unidad, mf_mfm, vunidad, cilindro, cabezal, kbps)
  1015. {
  1016.   unsigned char buffer[768];  /* ¡hasta 192 sectores! */
  1017.   static        sectores=-1,
  1018.                 pokete=0xE6, tsector=2, eformat=0, freset=0,
  1019.                 autogap=1, tunidad=4, gap=108, dmacnt=-1;
  1020.   int           i, b765;
  1021.   long          bytes;
  1022.   char          cad[32];
  1023.  
  1024.   ventana (ABRIR, 23, 3, 64, 23, CF, CFF);
  1025.  
  1026.   if (sp) {
  1027.       gotoxy (12,1);
  1028.       cputs("FORMATEO DE PISTA");
  1029.       }
  1030.     else {
  1031.       gotoxy (15,1);
  1032.       cputs("FORMAT TRACK");
  1033.       }
  1034.  
  1035.   gotoxy (2, 3); if (sp) cputs("Tamaño de sector:"); else cputs("Sector size:");
  1036.   gotoxy (2, 4); cputs("  0 -> 1-128 bytes    5 ->  4096 bytes");
  1037.   gotoxy (2, 5); cputs("  1 ->   256 bytes    6 ->  8192 bytes");
  1038.   gotoxy (2, 6); cputs("  2 ->   512 bytes    7 -> 16384 bytes");
  1039.   gotoxy (2, 7); cputs("  3 ->  1024 bytes    8 -> 32768 bytes");
  1040.   gotoxy (2, 8); cputs("  4 ->  2048 bytes    Val");
  1041.   if (sp) cputs("or: "); else cputs("ue: ");
  1042.   strcpy (cad, dec2strq (tsector));
  1043.   if (!input (cad, 1, 2, CF, CFF)) goto AbortaFormateo;
  1044.   tsector = atoi (cad);
  1045.  
  1046.   if (sectores==-1) { /* primera vez */
  1047.     switch (TipoDrive(unidad)) {
  1048.       case 2:  if (kbps==0) sectores = 15; else sectores=9; break;
  1049.       case 5:  if (kbps==3) sectores = 36;  /* sin break :-) */
  1050.       case 4:  if (kbps==0) sectores = 18;
  1051.                if ((kbps==1) || (kbps==2)) sectores=9; break;
  1052.       case 1:
  1053.       case 3:
  1054.       default: sectores = 9;  tunidad = 1; break;
  1055.       }
  1056.     if (!mf_mfm) sectores >>= 1;
  1057.     }
  1058.  
  1059.   gotoxy (2,10); if (sp) cputs("Sectores: "); else cputs("Sectors: ");
  1060.   strcpy (cad, dec3strq (sectores));
  1061.   if (!input (cad, 1, 3, CF, CFF)) goto AbortaFormateo;
  1062.   sectores = atoi (cad); if (sectores>192) sectores=192;
  1063.  
  1064.   gotoxy (2,12);
  1065.   if (sp) cputs("¿Calculo yo el GAP3? (S/N): ");
  1066.     else cputs("Do I adjust the GAP3? (Y/N): ");
  1067.   if (autogap) strcpy (cad, sp?"S":"Y"); else strcpy (cad, "N");
  1068.   if (!input (cad, 0, 1, CF, CFF)) goto AbortaFormateo;
  1069.   if ((cad[0] | 32) == 'n') autogap=0; else autogap=1;
  1070.  
  1071.   if (autogap) {
  1072.       gotoxy ( 2, 12); clreol();
  1073.       if (TipoDrive(unidad)!=-1)
  1074.           tunidad=TipoDrive(unidad);
  1075.         else {
  1076.           gotoxy (17, 11); cputs("1 -  360K");
  1077.           gotoxy (17, 12); cputs("2 -  1.2M");
  1078.           gotoxy (17, 13); cputs("3 -  720K");
  1079.           gotoxy (17, 14); cputs("4 - 1.44M");
  1080.           gotoxy (17, 15); cputs("5 - 2.88M");
  1081.           gotoxy ( 2, 17); if (sp) cputs("Indica el tipo de UNIDAD: ");
  1082.                              else cputs("Select DRIVE type: ");
  1083.  
  1084.           strcpy (cad, dec2strq (tunidad));
  1085.           if (!input (cad, 1, 2, CF, CFF)) goto AbortaFormateo;
  1086.           tunidad = atoi (cad);
  1087.           if (tunidad>5) { tunidad=4; goto AbortaFormateo; }
  1088.           for (i=11; i<=17; i++) { gotoxy (1, i); clreol(); }
  1089.           }
  1090.       if (tunidad==6) tunidad=5;  /* convención AMI */
  1091.       switch (tunidad) {
  1092.         case 1:
  1093.         case 3: switch (kbps) {
  1094.                   case 1:  bytes =  7500; break;
  1095.                   default: bytes =  6250; break;
  1096.                   }
  1097.                 break;
  1098.         case 2: switch (kbps) {
  1099.                   case 0:  bytes = 10416; break;
  1100.                   case 2:  bytes =  5208; break;
  1101.                   default: bytes =  6250; break;
  1102.                   }
  1103.                 break;
  1104.         case 4:
  1105.         case 5: switch (kbps) {
  1106.                   case 1:  bytes =  7500; break;
  1107.                   case 2:  bytes =  6250; break;
  1108.                   case 3:  bytes = 25000; break;
  1109.                   default: bytes = 12500; break;
  1110.                   }
  1111.                 break;
  1112.         }
  1113.       b765=62; if (!mf_mfm) { bytes >>= 1; b765 >>= 1; }
  1114.       gap = (bytes-((b765 + (128L << tsector)) * sectores)-146-32) / sectores;
  1115.       if (gap>255) gap=255;
  1116.       if (gap<1) {
  1117.         gap=1;
  1118.         gotoxy (10,12); if (sp) cputs("-> ¡No caben tantos sectores!");
  1119.                           else cputs("-> Too many sectors for track!");
  1120.         }
  1121.       gotoxy (2, 12); cputs("GAP3: "); cputs(dec5strq(gap));
  1122.       }
  1123.     else {
  1124.       gotoxy (2,12); clreol(); cputs("GAP3: ");
  1125.       strcpy (cad, dec3strq (gap));
  1126.       if (!input (cad, 1, 3, CF, CFF)) goto AbortaFormateo;
  1127.       gap = atoi (cad); if (gap>255) gap=255;
  1128.       }
  1129.  
  1130.   gotoxy (20,10); if (sp) cputs("Byte de relleno: "); else cputs("Fill byte: ");
  1131.   strcpy (cad, dec3strq (pokete));
  1132.   if (!input (cad, 1, 3, CF, CFF)) goto AbortaFormateo;
  1133.   pokete = atoi (cad); if (pokete>255) pokete=255;
  1134.  
  1135.   gotoxy (2, 14);
  1136.   if (sp)
  1137.       cputs("¿Usar valores normales? (S/N): ");
  1138.     else
  1139.       cputs("Format with standard values? (Y/N): ");
  1140.   if (eformat) strcpy (cad, "N"); else strcpy (cad, sp?"S":"Y");
  1141.   if (!input (cad, 0, 1, CF, CFF)) goto AbortaFormateo;
  1142.   if ((cad[0] | 32) == 'n') eformat=1; else eformat=0;
  1143.  
  1144.   gotoxy (2, 16);
  1145.   if (sp)
  1146.       cputs("¿Formateo normal sin reset? (S/N): ");
  1147.     else
  1148.       cputs("Normal format without reset? (Y/N): ");
  1149.   if (freset) strcpy (cad, "N"); else strcpy (cad, sp?"S":"Y");
  1150.   if (!input (cad, 0, 1, CF, CFF)) goto AbortaFormateo;
  1151.   if ((cad[0] | 32) == 'n') freset=1; else freset=0;
  1152.  
  1153.   if (freset) {
  1154.     if (dmacnt==-1) dmacnt=sectores<<2;
  1155.     gotoxy (2, 18);
  1156.     if (sp)
  1157.         cputs("Valor del contador del DMA: ");
  1158.       else
  1159.         cputs("Value for DMA count: ");
  1160.     strcpy (cad, dec5strq (dmacnt));
  1161.     if (!input (cad, 1, 5, CF, CFF)) goto AbortaFormateo;
  1162.     dmacnt = atoi (cad);
  1163.     }
  1164.  
  1165.   for (i=0; i<sectores; i++) {   /* tabla propuesta para formatear */
  1166.     buffer[i*4]=cilindro;
  1167.     buffer[i*4+1]=cabezal;
  1168.     buffer[i*4+2]=i+1;
  1169.     buffer[i*4+3]=tsector;
  1170.     }
  1171.  
  1172.   if (eformat)
  1173.     if (!EditarTablaFmt (buffer, sectores))  /* permitir su alteración */
  1174.       goto AbortaFormateo;
  1175.  
  1176.   clrscr();
  1177.   gotoxy (16, 9);
  1178.   if (sp) cputs("Formateando..."); else cputs("Formatting...");
  1179.  
  1180.   MotorOn (unidad);
  1181.   SeleccionarUnidad (unidad, vunidad);
  1182.   MotorOn (unidad);
  1183.  
  1184.   PreparaDma(0x4A, freset? dmacnt: sectores << 2, buffer);
  1185.  
  1186.   outfdc (0x0D | mf_mfm << 6);     /* comando para formatear */
  1187.   outfdc (cabezal << 2 | unidad);  /* byte 1 de dicho comando */
  1188.   outfdc (tsector);
  1189.   outfdc (sectores);
  1190.   outfdc (gap);
  1191.   outfdc (pokete);                 /* byte de relleno */
  1192.  
  1193.   if (freset) {
  1194.       EsperaDma0 (unidad);         /* con reset precario */
  1195.       ResetUnidad (unidad);        /* reset en condiciones */
  1196.       SeleccionarUnidad (unidad, vunidad);
  1197.       }
  1198.     else EsperarInt();
  1199.  
  1200.   ventana (CERRAR, 23, 3, 64, 23, 0, 0);
  1201.  
  1202.   if (!freset) Resultados (FORMATEAR, unidad, cabezal);
  1203.  
  1204.   goto FinFormateo;
  1205.  
  1206.   AbortaFormateo: ventana (CERRAR, 23, 3, 64, 23, 0, 0);
  1207.   FinFormateo: ;
  1208. }
  1209.  
  1210.  
  1211. int EditarTablaFmt (unsigned char *buffer, int numsect)
  1212. {
  1213.   static sector=1, cil=-1, cab=-1, sec=-1, tse=-1, valor=0, subop=3;
  1214.   int    i, opcion, opc;
  1215.   char   cad[32];
  1216.  
  1217.   do {
  1218.     clrscr();
  1219.     if (sp) {
  1220.         gotoxy (5,1);
  1221.         cputs("OPCIONES ESPECIALES DE FORMATEO");
  1222.         }
  1223.       else {
  1224.         gotoxy (10,1);
  1225.         cputs("SPECIAL FORMAT OPTIONS");
  1226.         }
  1227.     gotoxy (2,3); if (sp) cputs("Sectores:   "); else cputs("Sectors:    ");
  1228.     for (i=0; (i<numsect) && (i<66); i++) {
  1229.       cputs (dec3str(buffer[i*4+2]));
  1230.       putch(' ');
  1231.       }
  1232.     if (numsect>65) cputs("...");
  1233.  
  1234.     if (sp) {
  1235.         gotoxy (2, 11); cputs("Opciones:");
  1236.         gotoxy (2, 12); cputs("    1 - Introducir manualmente los 4");
  1237.         gotoxy (2, 13); cputs("        bytes de un sector.");
  1238.         gotoxy (2, 14); cputs("    2 - Modificar un cierto byte en");
  1239.         gotoxy (2, 15); cputs("        todos los sectores.");
  1240.         gotoxy (2, 16); cputs("  ESC - Cancelar orden de formateo.");
  1241.         gotoxy (2, 17); cputs("INTRO - Proceder con el formateo.");
  1242.         gotoxy (2, 18); cputs("        Elige: ");
  1243.         }
  1244.       else {
  1245.         gotoxy (2, 11); cputs("Options:");
  1246.         gotoxy (2, 12); cputs("    1 - To introduce one by each the 4");
  1247.         gotoxy (2, 13); cputs("        bytes of one sector.");
  1248.         gotoxy (2, 14); cputs("    2 - To  modify  one of the 4 bytes");
  1249.         gotoxy (2, 15); cputs("        in all sectors.");
  1250.         gotoxy (2, 16); cputs("  ESC - Cancel format command.");
  1251.         gotoxy (2, 17); cputs("INTRO - Run now format command.");
  1252.         gotoxy (2, 18); cputs("        Choose: ");
  1253.         }
  1254.  
  1255.     do opcion=Tecla();
  1256.       while (((opcion<'1') || (opcion>'3')) && (opcion!=27) && (opcion!=13));
  1257.  
  1258.     for (i=11; i<19; i++) { gotoxy (1, i); clreol(); }
  1259.  
  1260.     if (opcion=='1') {
  1261.         do {
  1262.           gotoxy (2, 11); if (sp) cputs("Sector a alterar: ");
  1263.                             else cputs("Sector to modify: ");
  1264.           strcpy (cad, dec3strq (sector));
  1265.           if (!input (cad, 1, 3, CF, CFF)) break;
  1266.           sector = atoi (cad); if (sector>255) sector=255;
  1267.           for (i=0; (i<numsect) && (buffer[i*4+2]!=sector); i++);
  1268.           if (buffer[i*4+2]!=sector) {
  1269.               gotoxy (2, 13);
  1270.               if (sp) cputs("Ese sector no existe.");
  1271.                 else cputs("Such sector does not exist.");
  1272.               }
  1273.             else {
  1274.               gotoxy (2, 13); if (sp) cputs ("Nº Cilindro   (anterior=");
  1275.                                 else cputs ("Cylinder number (previous=");
  1276.                               cputs (dec3str(buffer[i*4]));
  1277.                               cputs ("):  ");
  1278.                               if (cil==-1) cil=buffer[i*4];
  1279.                               strcpy (cad, dec3strq (cil));
  1280.                               if (!input (cad, 1, 3, CF, CFF)) break;
  1281.                               cil = atoi(cad); if (cil>255) cil=255;
  1282.               gotoxy (2, 14); if (sp) cputs ("Nº Cabezal    (anterior=");
  1283.                                 else cputs ("Head     number (previous=");
  1284.                               cputs (dec3str(buffer[i*4+1]));
  1285.                               cputs ("):  ");
  1286.                               if (cab==-1) cab=buffer[i*4+1];
  1287.                               strcpy (cad, dec3strq (cab));
  1288.                               if (!input (cad, 1, 3, CF, CFF)) break;
  1289.                               cab = atoi(cad); if (cab>255) cab=255;
  1290.               gotoxy (2, 15); if (sp) cputs ("Número sector (anterior=");
  1291.                                 else cputs ("Sector   number (previous=");
  1292.                               cputs (dec3str(buffer[i*4+2]));
  1293.                               cputs ("):  ");
  1294.                               if (sec==-1) sec=buffer[i*4+2];
  1295.                               strcpy (cad, dec3strq (sec));
  1296.                               if (!input (cad, 1, 3, CF, CFF)) break;
  1297.                               sec = atoi(cad); if (sec>255) sec=255;
  1298.               gotoxy (2, 16); if (sp) cputs ("Tamaño Sector (anterior=");
  1299.                                 else cputs ("Sector    size  (previous=");
  1300.                               cputs (dec3str(buffer[i*4+3]));
  1301.                               cputs ("):  ");
  1302.                               if (tse==-1) tse=buffer[i*4+3];
  1303.                               strcpy (cad, dec3strq (tse));
  1304.                               if (!input (cad, 1, 3, CF, CFF)) break;
  1305.                               tse = atoi(cad); if (tse>255) tse=255;
  1306.                               buffer[i*4]=cil;
  1307.                               buffer[i*4+1]=cab;
  1308.                               buffer[i*4+2]=sec;
  1309.                               buffer[i*4+3]=tse;  /* hechos cambios */
  1310.               }
  1311.           } while (0);  /* do-bobo, para poder salir con break ;-) */
  1312.         }
  1313.       else if (opcion=='2') {
  1314.         if (sp) {
  1315.             gotoxy (2, 11); cputs("Característica a cambiar: ");
  1316.             gotoxy (2, 12); cputs("  0 - Nº Cilindro");
  1317.             gotoxy (2, 13); cputs("  1 - Nº Cabezal");
  1318.             gotoxy (2, 14); cputs("  2 - Nº Sector");
  1319.             gotoxy (2, 15); cputs("  3 - Tamaño sector");
  1320.             gotoxy (2, 16); cputs("      Elige: ");
  1321.             }
  1322.           else {
  1323.             gotoxy (2, 11); cputs("Characteristic to modify: ");
  1324.             gotoxy (2, 12); cputs("  0 - Cylinder number");
  1325.             gotoxy (2, 13); cputs("  1 - Head number");
  1326.             gotoxy (2, 14); cputs("  2 - Sector number");
  1327.             gotoxy (2, 15); cputs("  3 - Sector size");
  1328.             gotoxy (2, 16); cputs("      Choose: ");
  1329.             }
  1330.         strcpy (cad, dec2strq (subop));
  1331.         if (input (cad, 1, 3, CF, CFF)) {
  1332.          subop = atoi (cad);
  1333.          if (subop>3)
  1334.              subop=3;
  1335.            else {
  1336.              for (i=11; i<17; i++) { gotoxy (1, i); clreol(); }
  1337.              gotoxy (2, 11); if (sp) cputs("Nuevo valor general: ");
  1338.                                else cputs("New general value: ");
  1339.              strcpy (cad, dec3strq (valor));
  1340.              if (input (cad, 1, 3, CF, CFF)) {
  1341.                valor = atoi (cad); if (valor>255) valor=255;
  1342.                for (i=0; i<numsect; i++) buffer[i*4+subop]=(char) valor;
  1343.                }
  1344.             }
  1345.           }
  1346.         }
  1347.   } while ((opcion!=27) && (opcion!=13));
  1348.  
  1349.   return (opcion==13);
  1350. }
  1351.  
  1352.  
  1353. void LeerIds (unidad, mf_mfm, cabezal, vunidad)
  1354. {
  1355.   unsigned long tmp[24], acu;
  1356.   int nec[24][7];
  1357.   unsigned i, j, lectura, antlectura, cnth, primeravez=0, tec;
  1358.  
  1359.   do {
  1360.     ventana (ABRIR, 23, 11, 58, 15, CIW, CFIW);
  1361.  
  1362.     gotoxy (3, 2);
  1363.     if (sp)
  1364.         cputs("Leyendo ID's... [ESC-Cancelar]");
  1365.       else
  1366.         cputs("Reading ID's... [ESC - Aborts]");
  1367.     CursorOff();
  1368.  
  1369.     MotorOn (unidad);  /* asegurar que el motor está en marcha */
  1370.     SeleccionarUnidad (unidad, vunidad);
  1371.     MotorOn (unidad);
  1372.  
  1373.     outportb (0x61, inportb(0x61) & 0xFD | 1);  /* inhibir sonido */
  1374.     outportb (0x43, 0xB4);                      /* contador 2 */
  1375.     outportb (0x42, 0xFF); outportb (0x42, 0xFF);  /* cuenta 0xFFFF */
  1376.  
  1377.     for (i=0; i<24; i++) {
  1378.  
  1379.       outfdc (0x0A | mf_mfm << 6);        /* comando 'Leer ID' */
  1380.       outfdc (cabezal << 2 | unidad);     /* byte 1 del comando */
  1381.  
  1382.       lectura=0xFFFF; cnth=0;    /* cuenta inicial */
  1383.  
  1384.       do {                       /* esperar interrupción */
  1385.         antlectura=lectura;
  1386.         outportb (0x43, 0x80);        /* enclavamiento */
  1387.         lectura=inportb(0x42);        /* parte baja de la cuenta */
  1388.         lectura|=inportb(0x42) << 8;  /* parte alta de la cuenta */
  1389.         if (lectura>antlectura) if (cnth++>8) break;  /* timeout */
  1390.       } while (!(peekb(0x40, 0x3E) & 0x80));
  1391.  
  1392.       pokeb (0x40, 0x3E, peekb (0x40, 0x3E) & 0x7F); /* reset int. */
  1393.  
  1394.       outportb (0x61, inportb(0x61) & 0xFE);  /* bajar GATE */
  1395.       outportb (0x61, inportb(0x61) | 1);     /* subir GATE */
  1396.  
  1397.       if (kbhit()) {
  1398.          tec = getch(); if (!tec) tec=getch() << 8;
  1399.          if (tec==27) {                             /* tecla ESC */
  1400.            ventana (CERRAR, 23, 11, 58, 15, 0, 0);
  1401.            goto fin_ids;
  1402.            }
  1403.          }
  1404.  
  1405.       for (j=0; j<7; j++)
  1406.         if ((nec[i][j]=infdc())==-1) break;
  1407.  
  1408.       if (cnth<9)
  1409.           tmp[i]=cnth*65535L + (65535-lectura);
  1410.         else {
  1411.           tmp[i]=0L;                           /* error */
  1412.           nec[i][0]=-1;                        /* no informar */
  1413.           pokeb (0x40, 0x40, 0xFF);     /* asegurar motor en marcha */
  1414.           }  /* porque probablemente se está perdiendo mucho tiempo */
  1415.     }
  1416.  
  1417.     outportb (0x61, inportb(0x61) & 0xFC);
  1418.  
  1419.     ventana (CERRAR, 23, 11, 58, 15, 0, 0);
  1420.     textcolor (CIMS); textbackground(CFI);
  1421.     if (!primeravez++) clrscr(); gotoxy (4,1);
  1422.     textcolor (CIC);
  1423.     textbackground (CFIC); if (sp) cputs("  Milisegundos   "); else cputs("  Milliseconds   ");
  1424.     textbackground (CFI); putch(' ');
  1425.     textbackground (CFIC); cputs(" Sector ");
  1426.     textbackground (CFI); putch('  ');
  1427.     textbackground (CFIC); if (sp) cputs("  Tamaño   "); else cputs("   Size    ");
  1428.     textbackground (CFI); putch('  ');
  1429.     textbackground (CFIC); if (sp) cputs(" Cilindro "); else cputs(" Cylinder ");
  1430.     textbackground (CFI); putch('  ');
  1431.     textbackground (CFIC); if (sp) cputs(" Cara "); else cputs(" Side ");
  1432.     textbackground (CFI); putch('  ');
  1433.     textbackground (CFIC); cputs(" ST0 ");
  1434.     textbackground (CFI); putch('  ');
  1435.     textbackground (CFIC); cputs(" ST1 ");
  1436.     textbackground (CFI); putch('  ');
  1437.     textbackground (CFIC); cputs(" ST2 ");
  1438.  
  1439.     textbackground (CFI);
  1440.     acu=0;
  1441.     for (j=0; j<23; j++) {  /* rechazar primera muestra */
  1442.       gotoxy (4, j+2); textcolor (CIMS);
  1443.       if (tmp[j+1] && tmp[j]) {
  1444.           acu+=tmp[j+1];
  1445.           cprintf("[%8.2f]%7.2f ", acu/1193.18, tmp[j+1]/1193.18);
  1446.           }
  1447.         else
  1448.           cprintf("       N.D.       ");
  1449.       if (nec[j][0]>=0) {
  1450.         textcolor (CIS);
  1451.         cputs("   "); cputs(dec3str(nec[j][5]));
  1452.         textcolor (CIT); cputs("   ");
  1453.         if (nec[j][6]<9)
  1454.             cputs(dec5str(128 << nec[j][6]));
  1455.           else
  1456.             cputs ("    ?");
  1457.         cputs(" ("); cputs(dec3str(nec[j][6])); putch(')');
  1458.  
  1459.         textcolor (CICC);
  1460.         cputs("    "); cputs(dec3str(nec[j][3]));
  1461.         cputs("      "); cputs(dec3str(nec[j][4]));
  1462.         textcolor (CIST);
  1463.         cputs ("    0x"); cputs(hex2str(nec[j][0]));
  1464.         cputs ("  0x"); cputs(hex2str(nec[j][1]));
  1465.         cputs ("  0x"); cputs(hex2str(nec[j][2]));
  1466.         }
  1467.         else {
  1468.           textcolor (CIMS);
  1469.           cputs("    ??       ??          ??       ??     ??    ??    ?? ");
  1470.           }
  1471.       }
  1472.  
  1473.       textcolor (CIB);
  1474.       if (sp) {
  1475.           gotoxy (17, 25);
  1476.           cputs("Pulse la BARRA ESPACIADORA para leer más ID's");
  1477.           }
  1478.         else {
  1479.           gotoxy (23, 25);
  1480.           cputs("Press SPACE BAR to read more ID's");
  1481.           }
  1482.       CursorOff();
  1483.       tec = Tecla();
  1484.   } while ((tec==32) || (tec=='5'));
  1485.  
  1486.   fin_ids:  MotorOff();
  1487. }
  1488.  
  1489.  
  1490. void Resultados (operacion, unidad, cabezal)
  1491. {
  1492.   int  xx, yy, res, t, st[3], str, bit;
  1493.   char sterr[2][10][40] =
  1494.     { {  "MA (Missing Address Mark)",
  1495.          "NW (Non Writable: write protect error)",
  1496.          "ND (No data)",
  1497.          "",
  1498.          "OR (Overrun)",
  1499.          "DE (Data Error)",
  1500.          "",
  1501.          "EN (End of cylinder)",
  1502.          },
  1503.       {  "MD (Missing Address Mark in Data Field",
  1504.          "BC (Bad Cylinder)",
  1505.          "",
  1506.          "",
  1507.          "WC (Wrong Cylinder)",
  1508.          "DD (Data Error in Data Field)",
  1509.          "CM (Control Mark)",
  1510.          "",
  1511.          }
  1512.     };
  1513.  
  1514.   ventana (ABRIR, 12, 7, 69, 22, CRS, CFRS);
  1515.  
  1516.   gotoxy (2, 1);
  1517.   switch (operacion) {
  1518.     case LEER:      if (sp) cputs ("RESULTADO LECTURA");
  1519.                       else cputs ("READ RESULTS");
  1520.                     break;
  1521.     case ESCRIBIR:  if (sp) cputs ("RESULTADO ESCRITURA");
  1522.                       else cputs ("WRITE RESULTS");
  1523.                     break;
  1524.     case FORMATEAR:  if (sp) cputs ("RESULTADO FORMATEO");
  1525.                       else cputs ("FORMAT RESULTS");
  1526.                     break;
  1527.     }
  1528.  
  1529.   xx=wherex(); yy=wherey();
  1530.  
  1531.   gotoxy (2, 3); cputs("[ST0 0x"); st[0]=res=infdc();
  1532.     if (res>=0) cputs(hex2str(res)); else cputs("??"); putch(']');
  1533.   if (res<0) {
  1534.       if (sp) {
  1535.           cputs ("   ¡El FDC no responde!");
  1536.           gotoxy (xx, yy);
  1537.           cputs (": ¡ERROR!");
  1538.           }
  1539.         else {
  1540.           cputs ("  FDC no answers!");
  1541.           gotoxy (xx, yy);
  1542.           cputs (": ERROR!");
  1543.           }
  1544.       }
  1545.     else {
  1546.       gotoxy (2, 4); cputs("[ST1 0x");
  1547.         st[1]=res=infdc(); if (res<0) st[1]=0; else st[1] &= 0xB7;
  1548.         if (res>=0) cputs(hex2str(res)); else cputs("??"); putch(']');
  1549.       gotoxy (xx, yy);
  1550.       if ((st[0] & 0xC0)==0)
  1551.           cputs (sp?": CORRECTO":": OK");
  1552.         else
  1553.           cputs (sp?": ¡ERROR!":": ERROR!");
  1554.       gotoxy (14, 3); cputs("[ST2 0x");
  1555.         st[2]=res=infdc(); if (res<0) st[2]=0; else st[2] &= 0x73;
  1556.         if (res>=0) cputs(hex2str(res)); else cputs("??"); putch(']');
  1557.       gotoxy (26, 3); if (sp) cputs("[Cilindro "); else cputs("[Cylinder ");
  1558.         res=infdc();
  1559.         if (res>=0) cputs(dec3str(res)); else cputs("??"); putch(']');
  1560.       gotoxy (26, 4); if (sp) cputs("[Cabezal  "); else cputs("[Head     ");
  1561.         res=infdc();
  1562.         if (res>=0) cputs(dec3str(res)); else cputs("??"); putch(']');
  1563.       gotoxy (42, 3); cputs("[Sector   ");
  1564.         res=infdc();
  1565.         if (res>=0) cputs(dec3str(res)); else cputs("??"); putch(']');
  1566.       gotoxy (42, 4); if (sp) cputs("[Tamaño   "); else cputs("[Size     ");
  1567.         res=infdc();
  1568.         if (res>=0) cputs(dec3str(res)); else cputs("??"); putch(']');
  1569.  
  1570.       outfdc (4);                      /* Leer ST3 */
  1571.       outfdc (cabezal << 2 | unidad);  /* byte 1 */
  1572.       gotoxy (14, 4); cputs("[ST3 0x"); res=infdc();
  1573.         if (res>=0) cputs(hex2str(res)); else cputs("??"); putch(']');
  1574.  
  1575.       gotoxy (2, wherey()+1);
  1576.  
  1577.       for (str=1; str<=2; str++)
  1578.         for (bit=0, t=1; bit<8; bit++, t <<= 1)
  1579.           if (st[str] & t) {
  1580.              gotoxy (2, wherey()+1);
  1581.              cputs ("ST"); putch(str+'0'); putch('(');
  1582.              putch(bit+'0'); cputs("): ");
  1583.              cputs (sterr[str-1][bit]);
  1584.              }
  1585.       }
  1586.  
  1587.   MotorOff(); CursorOff();
  1588.   while (kbhit()) getch(); while (!kbhit());  /* dejar tecla en buffer */
  1589.   if ((bioskey(1) & 0xFF)==27) getch();       /* excepto si es ESC */
  1590.   ventana (CERRAR, 12, 7, 69, 22, 0, 0);
  1591. }
  1592.  
  1593.  
  1594. void MostrarBuffer (char huge *buffer, unsigned *bytes)
  1595. {
  1596.   static   unsigned desp=0, nbytes=1, valor=0;
  1597.   static   parte=0;
  1598.   char     *pantalla;
  1599.   unsigned char huge *p;
  1600.   unsigned register x, off;
  1601.   unsigned y, t, i;
  1602.   int      partes;
  1603.   char     cad[32];
  1604.   char     hexa[16]={'0', '1', '2', '3', '4', '5', '6', '7',
  1605.                      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  1606.  
  1607.   textbackground (CFV); textcolor (CVMI); clrscr();
  1608.  
  1609.   window (1,18,80,25); textbackground (CFVM); textcolor (CVMM); clrscr();
  1610.   putch('┌'); for (x=1; x<79; x++) putch ('─'); putch('┐');
  1611.   for (y=2; y<8; y++) {
  1612.     gotoxy (1, y); putch('│'); gotoxy (80, y); putch('│');
  1613.     }
  1614.   putch('└'); for (x=1; x<79; x++) putch ('─');
  1615.   _wscroll=0; putch('┘'); _wscroll=1;
  1616.   textcolor (CVMI);
  1617.   gotoxy ( 3,3); if (sp) cputs("Cursores:   "); else cputs("Cursor keys:");
  1618.                  cputs(" ± 256 bytes");
  1619.   gotoxy ( 3,4); if (sp) cputs("AvPág/RePág:"); else cputs("PgUp/PgDn:  ");
  1620.                  cputs (" ± 512 bytes");
  1621.   gotoxy ( 3,5); if (sp) cputs("Inicio/Fin:  Principio/Final");
  1622.                  else cputs("Home/End:    First/Last");
  1623.   gotoxy ( 3,6); if (sp) cputs("Intro:       Nueva sección");
  1624.                  else cputs("Enter:       New section");
  1625.   gotoxy (33,3); if (sp) cputs(" Tab: Modificar bytes");
  1626.                  else cputs("Tab: Modify sector");
  1627.   gotoxy (33,4); if (sp) cputs(" 0:   Poner buffer a 0");
  1628.                  else cputs("0:   Set buffer to 0");
  1629.   gotoxy (33,5); if (sp) cputs(" X,R: Buffer con trama");
  1630.                  else cputs("X,R: Grid buffer");
  1631.   gotoxy (33,6); if (sp) cputs(" B:   Tamaño buffer");
  1632.                  else cputs("B:   Set buffer size");
  1633.   textcolor (CVMD);
  1634.   gotoxy (58,3); if (sp) cputs("Sección "); else cputs("Section ");
  1635.   if (sp) {
  1636.       gotoxy (58,4); cputs("Sector de       bytes"); }
  1637.     else {
  1638.       gotoxy (64,4); cputs("bytes sector"); }
  1639.  
  1640.   textcolor (CVMS);
  1641.   gotoxy (58,6); if (sp) cputs("ESC/ALT-X  Abandonar");
  1642.                  else cputs("ESC/ALT-X  Exit");
  1643.  
  1644.   window (1, 1,80,25);
  1645.  
  1646.   partes = (*bytes >> 8); if (*bytes & 0xFF) partes++;
  1647.  
  1648.   if (parte>=partes) parte=0;
  1649.  
  1650.   textbackground (CFV);  /* atributos de fondo */
  1651.   for (y=1; y<=16; y++) {
  1652.     gotoxy (3, y);
  1653.     textcolor (CVD); cputs ("      ");
  1654.     textcolor (CVH); cputs ("                        ");
  1655.     textcolor (CVS); cputs ("  ");
  1656.     textcolor (CVH); cputs ("                           ");
  1657.     textcolor (CVA); cputs ("                ");
  1658.     }
  1659.  
  1660.   do {
  1661.     p = &buffer[256*parte];
  1662.     for (y=0; y<256; y += 16, p += 16) {
  1663.       pantalla = MK_FP ((peekb(0x40, 0x49) & 0x7F) == 7 ? 0xB000:0xB800, 0);
  1664.       textcolor (CVD); textbackground (CFV);
  1665.       off = (p-buffer);
  1666.       if (off >= *bytes) {
  1667.         y >>= 4; for (i=0; i < (17-y)*80; i++) pantalla [(y*80+i) << 1]=' ';
  1668.         break;
  1669.         }
  1670.       pantalla += ((y/16) * 80 + 2 ) << 1;
  1671.       *pantalla=hexa[off >> 12];       pantalla+=2;
  1672.       *pantalla=hexa[(off >> 8) & 15]; pantalla+=2;
  1673.       *pantalla=hexa[(off >> 4) & 15]; pantalla+=2;
  1674.       *pantalla=hexa[off & 15];        pantalla+=2;
  1675.       *pantalla=':';                   pantalla+=6;
  1676.       for (x=0; x < 8; x++) {
  1677.         *pantalla=hexa[p[x] >> 4];     pantalla+=2;
  1678.         *pantalla=hexa[p[x] & 15];     pantalla+=4;
  1679.         }
  1680.       *pantalla='-';                   pantalla+=4;
  1681.       for (x=8; x < 16; x++) {
  1682.         *pantalla=hexa[p[x] >> 4];     pantalla+=2;
  1683.         *pantalla=hexa[p[x] & 15];     pantalla+=4;
  1684.         }
  1685.       pantalla+=4;
  1686.       for (x=0; x < 16; x++) { *pantalla=p[x]?p[x]:32; pantalla+=2; }
  1687.       }
  1688.     textcolor (CVMD); textbackground (CFVM); gotoxy (70,20);
  1689.     strcpy (cad, dec3strq(parte+1));
  1690.     cputs(cad); putch('/');
  1691.     strcpy (cad, dec3strq(partes));
  1692.     cputs(cad); cputs("   ");
  1693.     if (sp) gotoxy (68,21); else gotoxy (58, 21);
  1694.     cputs(dec5str(*bytes));
  1695.     CursorOff();
  1696.     t=Tecla();
  1697.     switch (t) {
  1698.       case '-':
  1699.       case 0x4800: parte--; break; /* UP */
  1700.       case '+':
  1701.       case 0x5000: parte++; if (parte>=partes) parte=partes-1; break; /* DN */
  1702.       case ' ':    parte++; if (parte>=partes) parte=0; break;
  1703.       case 0x4700: parte=0; break;        /* HOME */
  1704.       case 0x4F00: parte=partes-1; break; /* END */
  1705.       case 0x4900: parte-=2; break;       /* PGUP */
  1706.       case 0x5100: parte+=2; if (parte>=partes) parte=partes-1; break; /* PGDN */
  1707.       case '0':    t = partes << 8;
  1708.                    for (i=0; i < t; i++) buffer[i]=0; break;
  1709.       case 'x':
  1710.       case 'X':    t = partes << 8;
  1711.                    for (i=0; i < t; i++) buffer[i]=i; break;
  1712.       case 'r':
  1713.       case 'R':    t = partes << 8;
  1714.                    for (i=0; i < t; i++) buffer[i]=rnd(256); break;
  1715.       case 13:     ventana (ABRIR, 29, 9, 50, 11, CVNS, CFVNS);
  1716.                    if (sp) cputs (" Nueva sección: ");
  1717.                      else cputs (" New section: ");
  1718.                    strcpy (cad, dec3strq(parte+1));
  1719.                    if (input (cad, 1, 3, CVNS, CFVNS)) parte = atoi(cad)-1;
  1720.                    if (parte>=partes) parte=partes-1; if (parte==-1) parte++;
  1721.                    ventana (CERRAR, 29, 9, 50, 11, 0, 0);
  1722.                    break;
  1723.       case 'b':
  1724.       case 'B':    ventana (ABRIR, 21, 11, 56, 13, CVNB, CFVNB);
  1725.                    if (sp) cputs (" Nuevo tamaño del sector: ");
  1726.                      else cputs (" New sector size: ");
  1727.                    strcpy (cad, dec5strq(*bytes));
  1728.                    t=*bytes; /* bytes previos */
  1729.                    if (input (cad, 1, 5, CVNB, CFVNB)) *bytes = atol(cad);
  1730.                    if (*bytes > SMAX) *bytes=SMAX;
  1731.                    partes = (*bytes >> 8); if (*bytes & 0xFF) partes++;
  1732.                    if (parte>=partes) parte=partes-1; if (parte==-1) parte++;
  1733.                    ventana (CERRAR, 21, 11, 56, 13, 0, 0); CursorOff();
  1734.                    for (i=t; i < *bytes; i++) buffer[i]=0;
  1735.                    break;
  1736.       case 9:      ventana (ABRIR, 15, 7, 57, 11, CVMB, CFVMB);
  1737.                    if (sp) cputs (" Desplazamiento inicial (hex):    ");
  1738.                      else cputs (" Initial offset (hex):             ");
  1739.                    strcpy (cad, hex2str(desp/256));
  1740.                    strcat (cad, hex2str(desp % 256));
  1741.                    while (*cad == ' ') strcpy (cad, cad+1);
  1742.                    x = wherex(); y = wherey();
  1743.                    if (input (cad, 2, 4, CVMB, CFVMB)) {
  1744.                      desp = hextoi(cad);
  1745.                      if (desp < SMAX) {
  1746.                        gotoxy (x, y);
  1747.                        cputs(hex2str(desp/256)); cputs(hex2str(desp % 256));
  1748.                        gotoxy (2, 2);
  1749.                        if (sp) cputs ("Número de bytes a cambiar (dec): ");
  1750.                          else cputs ("Number of bytes to modify (dec): ");
  1751.                        strcpy (cad, dec5strq(nbytes));
  1752.                        if (input (cad, 1, 5, CVMB, CFVMB)) {
  1753.                          nbytes = atoi(cad);
  1754.                          gotoxy (2, 3);
  1755.                          if (sp) cputs ("Valor de relleno (hex):  ");
  1756.                            else cputs ("Fill byte (hex): ");
  1757.                          strcpy (cad, hex2str(valor));
  1758.                          while (*cad == ' ') strcpy (cad, cad+1);
  1759.                          if (input (cad, 2, 2, CVMB, CFVMB)) {
  1760.                            valor = hextoi(cad);
  1761.                            CursorOff(); /* dar sensación de aceptación */
  1762.                            for (i=desp; (i<desp+nbytes) && (i<SMAX); i++)
  1763.                              buffer[i]=valor;
  1764.                            }
  1765.                          }
  1766.                        }
  1767.                      }
  1768.                    ventana (CERRAR, 15, 7, 57, 11, 0, 0);
  1769.                    break;
  1770.       default: if ((t>='1') && (t<='9')) {
  1771.                  parte = t - '0' - 1;
  1772.                  if (parte>=partes) parte=partes-1; if (parte==-1) parte++;
  1773.                  }
  1774.                break;
  1775.       }
  1776.     if (parte<0) parte=0;
  1777.   } while ((t != 0x1B) && (t != 0x2D00));
  1778. }
  1779.  
  1780.  
  1781. void MotorOn (unidad)
  1782. {
  1783.   int i;
  1784.  
  1785.       /**** Evitar que la BIOS pare el motor (al menos en 14") ****/
  1786.  
  1787.   pokeb(0x40,0x40,0xFF);
  1788.  
  1789.       /**** Si no lo está, ponerlo en marcha y esperar 1 segundo ****/
  1790.  
  1791.   if (((i=peekb(0x40, 0x3F)) & (1 << unidad))==0) {
  1792.     outportb (FD_DOR, 1<<(unidad+4) | 4+8 | unidad);
  1793.     pokeb (0x40, 0x3F, i | (1 << unidad));
  1794.     delay (1000);
  1795.     pokeb(0x40,0x40,0xFF);
  1796.     }
  1797. }
  1798.  
  1799.  
  1800. void MotorOff()
  1801. {
  1802.   pokeb(0x40,0x40,55);  /* la BIOS lo detendrá en 55/18.2 segundos */
  1803. }
  1804.  
  1805.  
  1806. void outfdc (unsigned char dato)     /* enviar byte al FDC */
  1807. {                                    /* no esperando más de 440 ms */
  1808.   int t, i=0, rd;
  1809.  
  1810.   do {
  1811.     i++; t=peekb(0x40, 0x6C);
  1812.     while ((t==peekb(0x40, 0x6C)) && ((rd=inportb(FD_STATUS)>>7)==0));
  1813.   } while ((i<8) && !rd);
  1814.  
  1815.   if (rd) outportb (FD_DATA, dato);
  1816. }
  1817.  
  1818.  
  1819. int infdc()         /* leer byte del FDC */
  1820. {                   /* no esperando más de 440 ms */
  1821.   int t, i=0, rd;
  1822.  
  1823.   do {
  1824.     i++; t=peekb(0x40, 0x6C);
  1825.     while ((t==peekb(0x40, 0x6C)) && ((rd=inportb(FD_STATUS)>>7)==0));
  1826.   } while ((i<8) && !rd);
  1827.  
  1828.   if (rd) return (inportb (FD_DATA)); else return (-1);  /* fallo */
  1829. }
  1830.  
  1831.  
  1832. void EsperarInt()    /* Esperar interrupción no más de 2 seg. */
  1833. {
  1834.   int t, i=0;
  1835.  
  1836.   do {
  1837.     i++; t=peekb(0x40, 0x6C);
  1838.     while ((t==peekb(0x40, 0x6C)) && (!(peekb(0x40, 0x3E) & 0x80)));
  1839.   } while ((i<37) && (!(peekb(0x40, 0x3E) & 0x80)));
  1840.  
  1841.   pokeb (0x40, 0x3E, peekb (0x40, 0x3E) & 0x7F);
  1842. }
  1843.  
  1844.  
  1845. void PreparaDma (rmodo, bytes, buffer)
  1846. unsigned rmodo, bytes;
  1847. char huge *buffer;
  1848. {
  1849.   unsigned long dir;
  1850.   unsigned dmapag, dmaoff;
  1851.  
  1852.   dir = ((unsigned long) FP_SEG(buffer) <<4) + FP_OFF(buffer);
  1853.   dmapag = dir >> 16;  dmaoff = dir & 0xFFFF;
  1854.  
  1855.   outportb (0x81, dmapag);      /* registro de página del canal 2 */
  1856.   outportb (0xB, rmodo);        /* programar registro de modo */
  1857.   outportb (0xC, 0);            /* clear first/last flip-flop */
  1858.   outportb (4,dmaoff & 0xFF);   /* dirección base (parte baja) */
  1859.   outportb (4,dmaoff >> 8);     /* dirección base (parte alta) */
  1860.   outportb (5,(bytes-1) % 256); /* nº de bytes menos 1 (parte baja) */
  1861.   outportb (5,(bytes-1) / 256); /* nº de bytes menos 1 (parte alta) */
  1862.   outportb (0xA, 2);            /* habilitar canal 2 */
  1863. }
  1864.  
  1865.  
  1866. char *hex2str (int num)
  1867. {
  1868.   static char cad[32];
  1869.   char   hexa[16]={'0', '1', '2', '3', '4', '5', '6', '7',
  1870.                    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  1871.  
  1872.   cad[0]=hexa[num >> 4];
  1873.   cad[1]=hexa[num & 15];
  1874.   cad[2]=0;
  1875.  
  1876.   return (cad);
  1877. }
  1878.  
  1879.  
  1880. int hextoi (char *cad)
  1881. {
  1882.   unsigned num=0, error=0;
  1883.   char     *p;
  1884.  
  1885.   p=cad; while (*p) { if (*p > '9') *p = (*p & 0xDF) - 7; p++; }
  1886.   p=cad; while (*p && !error) if ((*p<'0') || (*p>'?')) error++; else p++;
  1887.   p=cad; while (*p) { num <<= 4; num |= *p-'0'; p++; }
  1888.  
  1889.   if (!error) return (num); else return(0);
  1890. }
  1891.